#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import subprocess
import time
import sys
import webbrowser
import socket
import os
import shutil

# 配置参数
HOST = "127.0.0.1"
PORT = 8080
TIMEOUT = 30  # 秒

def check_port(host, port):
    """
    检查指定主机和端口是否正在监听
    """
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        sock.settimeout(1)
        result = sock.connect_ex((host, port))
        return result == 0

def wait_for_port(host, port, timeout):
    """
    等待指定端口在超时时间内开始监听
    """
    start_time = time.time()
    while time.time() - start_time < timeout:
        if check_port(host, port):
            return True
        time.sleep(0.5)
    return False

def terminate_process(process):
    """
    终止指定进程
    """
    if process.poll() is None:  # 如果进程仍在运行
        process.terminate()
        try:
            process.wait(timeout=5)  # 等待最多5秒
        except subprocess.TimeoutExpired:
            process.kill()  # 强制杀死进程
            process.wait()

def is_command_available(command):
    """
    检查命令是否可用
    """
    return shutil.which(command) is not None

def run_command(command, cwd=None):
    """
    运行命令并返回进程对象
    """
    print(f"执行命令: {command}")
    try:
        # 设置环境变量以正确处理中文路径
        env = os.environ.copy()
        env['GOENV'] = 'off'
        
        process = subprocess.Popen(
            command,
            shell=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            cwd=cwd,
            text=True,
            encoding='utf-8',  # 设置编码为UTF-8
            errors='replace'    # 遇到编码错误时替换字符
        )
        return process
    except Exception as e:
        print(f"执行命令失败: {e}")
        sys.exit(1)

def main():
    # 获取当前工作目录
    work_dir = os.getcwd()
    backend_dir = os.path.join(work_dir, "backend")
    
    # 检查backend目录是否存在
    if not os.path.exists(backend_dir):
        print(f"错误: backend目录不存在 ({backend_dir})")
        sys.exit(1)
    
    # 检查端口是否已被占用
    print(f"检查端口 {HOST}:{PORT} 是否被占用...")
    if check_port(HOST, PORT):
        print(f"❌ 错误: 端口 {HOST}:{PORT} 已被占用")
        print("请检查是否有其他程序正在使用该端口，或修改配置文件中的端口号")
        sys.exit(1)
    
    print("开始执行后端服务部署...")
    
    # 1. Swagger初始化 (先检查swag是否已安装，再初始化)
    print("步骤1: 初始化Swagger文档...")
    
    # 检查swag命令是否可用
    if not is_command_available("swag"):
        print("Swag命令未找到，正在安装...")
        process = run_command("go install github.com/swaggo/swag/cmd/swag@latest", cwd=backend_dir)
        stdout, stderr = process.communicate()
        
        if process.returncode != 0:
            print(f"Swag工具安装失败: {stderr}")
            sys.exit(1)
        print("Swag工具安装完成")
    else:
        print("Swag命令已存在，跳过安装")
    
    # 初始化swagger文档
    process = run_command("swag init -g cmd/main.go", cwd=backend_dir)
    stdout, stderr = process.communicate()
    
    if process.returncode != 0:
        print(f"Swagger初始化失败: {stderr}")
        sys.exit(1)
    
    print("Swagger文档初始化完成")
    
    # 2. 编译Go程序
    print("步骤2: 编译Go程序...")
    process = run_command("go build -o disk-monitoring.exe ./cmd/main.go", cwd=backend_dir)
    stdout, stderr = process.communicate()
    
    if process.returncode != 0:
        print(f"编译失败: {stderr}")
        sys.exit(1)
    
    print("Go程序编译完成")
    
    # 3. 运行程序
    print("步骤3: 启动服务...")
    executable = os.path.join(backend_dir, "disk-monitoring.exe")
    process = run_command(executable, cwd=backend_dir)
    
    # 注册退出处理函数，确保程序退出时终止子进程
    import atexit
    atexit.register(terminate_process, process)
    
    # 等待端口监听
    print(f"等待服务在 {HOST}:{PORT} 上启动 (超时: {TIMEOUT} 秒)...")
    if wait_for_port(HOST, PORT, TIMEOUT):
        print("服务启动成功!")
        
        # 打开浏览器访问
        url = f"http://{HOST}:{PORT}/swagger/index.html"
        print(f"正在打开 {url}")
        webbrowser.open(url)
        
        # 等待用户手动终止程序
        try:
            stdout, stderr = process.communicate()
            if process.returncode != 0:
                print(f"程序运行出错: {stderr}")
        except KeyboardInterrupt:
            print("\n收到终止信号，正在关闭服务...")
    else:
        print(f"服务启动超时 ({TIMEOUT} 秒)")
        terminate_process(process)
        sys.exit(1)
    
    # 如果程序正常退出
    terminate_process(process)
    print("服务已关闭")

if __name__ == "__main__":
    main()